# Entry point for the kharlia application
# NOTE: No global imports for this file

from __future__ import print_function
from __future__ import unicode_literals

DEFAULT_BASE_DIR = '..',
DEFAULT_BIN_DIR = 'bin',

PRINT_VERSION = True
PRINT_INITIAL_PATH = False
PRINT_PATH = True
PRINT_ARGV = True
PRINT_GCREPORT = True

REMOVE_DEFAULT_PATHS = True
PYDEVD_ENABLED = True
PYDEVD_SUSPEND = False

DEBUG_UNREACHABLES = False
        
def configure_path():
    import sys, os
    from os.path import join
    
    # Set standard paths relative to CWD
    cwd = os.getcwd()
    sys.path = [
        join(cwd, 'app'),
        join(cwd, 'lib'),
        join(cwd, 'lib', 'std'),
        ]
    
    # Scan folders in the path for zip files and add them to the path
    for i in sys.path:
        if i.endswith('.zip'):
            continue
        try:
            files = os.listdir(i)
            for e in files:
                if e.endswith('.zip'):
                    sys.path.append(join(i, e))
        except:
            pass

def main(appid=None):
    '''
    Run the Kharlia client. This function should be called on a
    default execution of Kharlia.exe
    '''
    import sys
    import gc
    import argparse
    #import os
    #from os import path

    if PRINT_VERSION:
        print('Python', sys.version, 'on', sys.platform)

    if PRINT_ARGV:
        print('argv:')
        for i in sys.argv:
            print(' ', i)
    
    if sys.platform != 'win32':
        raise RuntimeError('unsupported platform')
    
    # Python version check, major and minor
    if sys.version_info[0] != 2 or sys.version_info[1] != 7:
        raise RuntimeError('unsupported Python version, must be 2.7')

    # Argument parsing
    parser = argparse.ArgumentParser(prefix_chars='-+')
    parser.add_argument('--appid', nargs=1, metavar='ID', type=str)
    parser.add_argument('--pydevd', nargs=1, metavar='PATH', type=str)
        
    result, remargs = parser.parse_known_args()
    
    # Extract appid from command line
    if appid is None:
        if result.appid is None:
            raise ValueError('unspecified appid')
        appid = result.appid[0]

    if PRINT_INITIAL_PATH:
        print('initial path:')
        for i in sys.path:
            print(' ', i)

    # Preprend bin directory to PATH environment variable       
    #head, tail = path.split(__file__)
    #basedir = path.abspath(path.join(head, *DEFAULT_BASE_DIR))
    #os.chdir(basedir)
    #print('basedir:', basedir)
    #bindir = path.join(basedir, *DEFAULT_BIN_DIR)
    #os.environ['PATH'] = ''.join((bindir, ';', os.environ['PATH']))
    #print('bindir:', bindir)

    # Configure the python module path
    configure_path()

    if PRINT_PATH:
        print('path:')
        for i in sys.path:
            print(' ', i)
    
    # Connect to the PyDev debugger
    trace = None
    usingpydev = False
    if PYDEVD_ENABLED:
        if result.pydevd is not None:
            sys.path.append(result.pydevd[0])
            import pydevd
            pydevd.settrace(suspend=PYDEVD_SUSPEND)
            # Retrieve the global trace dispatch function
            # Simply using sys.gettrace() would yield the
            # per-frame trace function which would cause
            # problems later.
            trace = pydevd.GetGlobalDebugger().trace_dispatch
            usingpydev = True
    
    if DEBUG_UNREACHABLES:
        gc.set_debug(gc.DEBUG_SAVEALL)

    # path must be configured before importing
    from kharlia.core import CApp
    app = CApp(appid)
    app.Run(remargs, trace, usingpydev)
    del app
    del trace
    
    # Print GC info
    if PRINT_GCREPORT:
        print('gc: counts: ', gc.get_count())
        if DEBUG_UNREACHABLES:
            print('gc: unreachable types:')
            types = set()
            for u in gc.garbage:
                t = type(u)
                if t not in types:
                    print(' ', t)
                    types.add(t)   
        else:
            print('gc: collecting...')
            urc = gc.collect()
            while urc > 0:  
                print('gc: unreachables count:', urc)
                urc = gc.collect()
            print('gc: garbage:')
            for i in gc.garbage:
                print(' ', i)

if __name__ == '__main__':
    main()